#!/usr/bin/env python3
"""
项目完整性检查脚本

检查项目文件完整性、导入依赖和配置一致性
"""

import ast
import sys
from pathlib import Path
from typing import List, Dict, Set

def check_imports():
    """检查导入语句的一致性"""
    print("🔍 检查导入依赖...")
    
    src_dir = Path("src")
    issues = []
    
    for py_file in src_dir.rglob("*.py"):
        try:
            with open(py_file, 'r', encoding='utf-8') as f:
                content = f.read()
            
            tree = ast.parse(content)
            
            for node in ast.walk(tree):
                if isinstance(node, ast.ImportFrom):
                    if node.module and node.module.startswith('src.'):
                        # 检查内部导入
                        module_path = node.module.replace('.', '/')
                        if not (Path(module_path + '.py').exists() or 
                               Path(module_path + '/__init__.py').exists()):
                            issues.append(f"{py_file}: 导入模块不存在 - {node.module}")
        
        except Exception as e:
            issues.append(f"{py_file}: 解析错误 - {e}")
    
    if issues:
        print("❌ 发现导入问题:")
        for issue in issues:
            print(f"  - {issue}")
    else:
        print("✅ 导入依赖检查通过")
    
    return issues

def check_required_files():
    """检查必需文件是否存在"""
    print("\n🔍 检查必需文件...")
    
    required_files = [
        "src/__init__.py",
        "src/main.py",
        "src/core/__init__.py",
        "src/core/config.py",
        "src/core/database.py",
        "src/core/redis.py",
        "src/core/logger.py",
        "src/models/__init__.py",
        "src/models/user.py",
        "src/models/channel.py",
        "src/models/video.py",
        "src/models/category.py",
        "src/services/__init__.py",
        "src/services/auth_service.py",
        "src/services/youtube_service.py",
        "src/services/user_service.py",
        "src/services/category_service.py",
        "src/services/video_service.py",
        "src/services/search_service.py",
        "src/api/__init__.py",
        "src/api/v1/__init__.py",
        "src/api/v1/auth.py",
        "src/api/v1/users.py",
        "src/api/v1/categories.py",
        "src/api/v1/channels.py",
        "src/api/v1/videos.py",
        "src/api/v1/search.py",
        "src/api/v1/monitoring.py",
        "src/api/dependencies.py",
        "src/utils/__init__.py",
        "src/utils/exceptions.py",
        "src/utils/cache.py",
        "src/utils/rate_limiter.py",
        "src/utils/performance.py",
        "src/utils/database_optimization.py",
        "requirements.txt",
    ]
    
    missing_files = []
    for file_path in required_files:
        if not Path(file_path).exists():
            missing_files.append(file_path)
    
    if missing_files:
        print("❌ 缺失文件:")
        for file_path in missing_files:
            print(f"  - {file_path}")
    else:
        print("✅ 必需文件检查通过")
    
    return missing_files

def check_exception_consistency():
    """检查异常类使用的一致性"""
    print("\n🔍 检查异常类一致性...")
    
    # 从exceptions.py中获取定义的异常类
    exceptions_file = Path("src/utils/exceptions.py")
    defined_exceptions = set()
    
    if exceptions_file.exists():
        with open(exceptions_file, 'r', encoding='utf-8') as f:
            content = f.read()
        
        tree = ast.parse(content)
        for node in ast.walk(tree):
            if isinstance(node, ast.ClassDef) and node.name.endswith('Exception'):
                defined_exceptions.add(node.name)
    
    # 检查各文件中使用的异常类
    used_exceptions = set()
    issues = []
    
    src_dir = Path("src")
    for py_file in src_dir.rglob("*.py"):
        if py_file.name == "exceptions.py":
            continue
            
        try:
            with open(py_file, 'r', encoding='utf-8') as f:
                content = f.read()
            
            # 简单的文本搜索异常使用
            for exception in defined_exceptions:
                if exception in content:
                    used_exceptions.add(exception)
        
        except Exception as e:
            issues.append(f"{py_file}: 读取错误 - {e}")
    
    # 检查是否有未定义的异常被使用
    undefined_used = used_exceptions - defined_exceptions
    if undefined_used:
        print("❌ 使用了未定义的异常:")
        for exc in undefined_used:
            print(f"  - {exc}")
    else:
        print("✅ 异常类一致性检查通过")
    
    return issues

def check_api_consistency():
    """检查API路由的一致性"""
    print("\n🔍 检查API路由一致性...")
    
    issues = []
    
    # 检查API路由注册
    v1_init = Path("src/api/v1/__init__.py")
    if v1_init.exists():
        with open(v1_init, 'r', encoding='utf-8') as f:
            content = f.read()
        
        expected_routes = [
            "auth_router",
            "users_router", 
            "categories_router",
            "channels_router",
            "videos_router",
            "search_router",
            "monitoring_router"
        ]
        
        for route in expected_routes:
            if route not in content:
                issues.append(f"API路由 {route} 未在v1/__init__.py中注册")
    
    if issues:
        print("❌ API路由问题:")
        for issue in issues:
            print(f"  - {issue}")
    else:
        print("✅ API路由一致性检查通过")
    
    return issues

def check_database_models():
    """检查数据库模型的一致性"""
    print("\n🔍 检查数据库模型...")
    
    models_dir = Path("src/models")
    issues = []
    
    if not models_dir.exists():
        issues.append("models目录不存在")
        return issues
    
    # 检查__init__.py中的模型导入
    models_init = models_dir / "__init__.py"
    if models_init.exists():
        with open(models_init, 'r', encoding='utf-8') as f:
            init_content = f.read()
        
        # 检查主要模型是否被导入
        expected_models = ["User", "Channel", "Video", "Category"]
        for model in expected_models:
            if model not in init_content:
                issues.append(f"模型 {model} 未在models/__init__.py中导入")
    
    if issues:
        print("❌ 数据库模型问题:")
        for issue in issues:
            print(f"  - {issue}")
    else:
        print("✅ 数据库模型检查通过")
    
    return issues

def main():
    """主检查函数"""
    print("🚀 开始项目完整性检查...\n")
    
    all_issues = []
    
    # 执行各项检查
    all_issues.extend(check_required_files())
    all_issues.extend(check_imports()) 
    all_issues.extend(check_exception_consistency())
    all_issues.extend(check_api_consistency())
    all_issues.extend(check_database_models())
    
    print("\n" + "="*50)
    
    if all_issues:
        print(f"❌ 检查完成，发现 {len(all_issues)} 个问题需要修复")
        print("\n📋 问题汇总:")
        for i, issue in enumerate(all_issues, 1):
            print(f"  {i}. {issue}")
        sys.exit(1)
    else:
        print("✅ 项目完整性检查全部通过！")
        print("🎉 项目已就绪，可以启动应用")
        sys.exit(0)

if __name__ == "__main__":
    main()